<template>
  <div id="app">
    <el-backtop></el-backtop>
    <el-container direction="vertical">
      <el-header>
        <h3>静态资源服务器</h3>
      </el-header>
      <el-tabs
        addable
        editable
        stretch
        v-model="currentIndex"
        type="card"
        @tab-remove="deleteTask"
        @tab-add="addTask"
      >
        <el-tab-pane
          v-for="(item, index) in myTasks"
          :key="index"
          :name="index.toString()"
          :label="item.name"
          :lazy="true"
          v-loading="item.loading"
        >
          <transition name="el-fade-in-linear">
            <el-main>
              <div
                class="show-loading"
                v-if="item.success"
                v-loading="true"
                element-loading-text="服务器正在运行"
                element-loading-spinner="el-icon-loading"
                :span="24"
              ></div>

              <el-form ref="form">
                <el-form-item>
                  <el-input :disabled="item.success" v-model="item.name" placeholder="服务器名称">
                    <span slot="prepend">服务器名称</span>
                  </el-input>
                </el-form-item>
                <el-form-item>
                  <el-input :disabled="item.success" v-model="item.localPath" placeholder="本地路径">
                    <span slot="prepend">静态资源路径</span>
                    <el-button
                      :disabled="item.success"
                      class="el-icon-folder-opened"
                      :data-id="index"
                      slot="append"
                      plain
                      size="small"
                      @click="selectLocalPath"
                    ></el-button>
                  </el-input>
                </el-form-item>
                <el-form-item>
                  <el-input-number
                    :disabled="item.success"
                    v-model.number="item.portNumber"
                    :step="1"
                    :max="65536"
                    :min="0"
                    step-strictly
                    placeholder="端口号"
                  >
                    <span slot="prepend">静态资源路径</span>
                  </el-input-number>
                </el-form-item>
              </el-form>
              <el-row v-if="!item.success">
                <el-col :span="24">
                  <el-button
                    :data-id="currentIndex"
                    class="el-icon-switch-button"
                    type="primary"
                    @click="startService"
                  >
                    {{
                    `启动服务器 (端口 :${item.portNumber})`
                    }}
                  </el-button>
                </el-col>
              </el-row>
              <el-form class="sec-form" v-if="item.success">
                <el-form-item>
                  <el-input v-model="additionText" placeholder="后缀或文件名">
                    <span slot="prepend">后缀</span>
                  </el-input>
                </el-form-item>
              </el-form>
              <el-main v-for="(element, index) in networkInterfaces" :key="index">
                <el-row v-if="undefined!== element && undefined !==element.address && item.success">
                  <el-col :span="24">
                    <el-button
                      :disabled="!item.success"
                      @click="openUrl"
                      type="primary"
                      size="small"
                      plain
                    >
                      http://{{ element.address }}:{{
                      item.portNumber
                      }}{{ additionText }}
                    </el-button>
                  </el-col>
                </el-row>
                <el-row v-if="undefined!== element && undefined !==element.address && item.success">
                  <el-col :span="24">
                    <vue-qr
                      :text="
				    	`http://${element.address}:${item.portNumber}${additionText}`
						"
                    ></vue-qr>
                  </el-col>
                </el-row>
              </el-main>
            </el-main>
          </transition>
        </el-tab-pane>
      </el-tabs>
    </el-container>
  </div>
</template>

<script>
const net = require("net");
const {
  desktopCapturer,
  ipcRenderer,
  remote,
  webFrame,
  clipboard,
  shell
} = require("electron");
const express = require("express");
const path = require("path");
var os = require("os");
const fs = require("fs-extra");
import VueQr from "vue-qr";

export default {
  name: "app",
  data: function() {
    return {
      currentIndex: 0,
      additionText: "/index.html",
      myTasks: [
        {
          name: "服务器1",
          localPath: remote.app.getPath("documents"),
          portNumber: Math.round(Math.random() * 65536),
          app: express(),
          success: false,
          loading: false
        },
        {
          name: "服务器2",
          localPath: remote.app.getPath("appData"),
          portNumber: Math.round(Math.random() * 65536),
          app: express(),
          success: false,
          loading: false
        },
        {
          name: "服务器3",
          localPath: remote.app.getPath("cache"),
          portNumber: Math.round(Math.random() * 65536),
          app: express(),
          success: false,
          loading: false
        },
        {
          name: "服务器4",
          localPath: remote.app.getPath("exe"),
          portNumber: Math.round(Math.random() * 65536),
          app: express(),
          success: false,
          loading: false
        }
      ]
    };
  },
  computed: {
    networkInterfaces: function() {
      const _net = Object.values(os.networkInterfaces());
      var temp = [];
      _net.forEach(element1 => {
        element1.forEach(element2 => {
          if (
            element2.family !== undefined &&
            element2.family.toUpperCase() === "IPV4"
          ) {
            temp.push(element2);
          }
        });
      });
      // console.log("networkInterfaces", temp);
      return temp;
    }
  },
  components: {
    VueQr
  },
  watch: {
    myTasks: function(newVal) {
      // console.log(newVal);
    },
    currentIndex: function(newVal) {
      // console.log(newVal);
    }
  },
  methods: {
    addTask: function(e) {
      this.myTasks.push({
        name: "服务器" + (this.myTasks.length + 1),
        localPath: remote.app.getPath("documents"),
        portNumber: Math.round(Math.random() * 65536),
        app: express(),
        success: false,
        loading: false
      });
      this.currentIndex = (this.myTasks.length - 1).toString();
    },
    deleteTask: function(e) {
      if (!this.myTasks[e].success && !this.myTasks[e].loading) {
        this.myTasks.splice(e, 1);
        this.currentIndex = (e - 1).toString();
      } else {
        this.$message.error(`${this.myTasks[e].name}已经在运行, 无法删除`);
      }
    },
    selectLocalPath: async function(e) {
      let i = parseInt(e.target.dataset.id);
      let res = await remote.dialog.showOpenDialog({
        properties: ["openDirectory"]
      });
      if (!res.canceled) {
        this.$set(this.myTasks[i], "localPath", res.filePaths[0]);
      }
      // console.log(res);
    },
    startService: async function(e) {
      const that = this;
      let i = parseInt(this.currentIndex);
      let _app = this.myTasks[i].app;
      let _path = path.normalize(this.myTasks[i].localPath);
      let _stat = fs.pathExistsSync;
      var _port = this.myTasks[i].portNumber;
      var _ok = false;
      that.$set(that.myTasks[i], "loading", true);
      setTimeout(() => {
        if (_ok === true) {
        } else {
          that.$set(that.myTasks[i], "success", false);
          that.$set(that.myTasks[i], "loading", false);
          that.$notify({
            title: "失败",
            message: `开启<${that.myTasks[i].name}>失败, 端口可能被占用`,
            type: "error"
          });
        }
      }, 3000);
      if (_stat) {
        _app.use("/", express.static(_path));
        try {
          _app.listen(_port, res => {
            // console.log(res);
            console.log(`App listening at port ${_port}`);
            that.$set(that.myTasks[i], "success", true);
            that.$set(that.myTasks[i], "loading", false);
            _ok = true;
            that.$notify({
              title: "成功",
              message: `开启<${that.myTasks[i].name}>成功`,
              type: "success"
            });
          });
        } catch (err) {
          that.$set(that.myTasks[i], "success", false);
          that.$set(that.myTasks[i], "loading", false);
        }
      } else {
        that.$notify({
          title: "失败",
          message: `开启<${that.myTasks[i].name}>失败, 路径不存在`,
          type: "error"
        });
      }
    },
    pauseServiceClick: async function(e) {
      const that = this;
      let i = parseInt(this.currentIndex);
      let _app = this.myTasks[i].app;
      // console.log(_app);
      that.$set(that.myTasks[i], "success", false);
    },
    pauseService: async function(index) {},
    portInUse: async function(port) {
      return new Promise((resolve, reject) => {
        let server = net.createServer().listen(port);
        // console.log(server);
        server.on("listening", function() {
          // console.log(`the server is running on port ${port}`);
          server.close();
          resolve(port);
        });
        server.on("error", function(err) {
          // console.log(`this port ${port} is occupied.try another.`);
          if (err.code == "EADDRINUSE") {
            port++;
            reject(err);
          }
        });
      });
    },
    openUrl: function(e) {
      // console.log(e);
      try {
        shell.openExternal(e.target.textContent);
      } catch (error) {
        console.warn(error);
      }
    }
  }
};
</script>

<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
.el-col {
  margin-top: 5px;
  margin-bottom: 5px;
}
.el-button {
  width: 80%;
  margin-top: 5px;
  margin-bottom: 5px;
}
.sec-form {
  margin-top: 20px;
}
.show-loading {
  height: 80px;
}
</style>
